<template>
  <AdVxeModal
    v-bind="$attrs"
    @register="register"
    :id="'send-email-modal'"
    :title="sendTitle"
    :close-func="handleClose"
    @ok="handleOk"
    width="30%"
  >
    <Form
      class="p-4 enter-x"
      :label-col="labelCol"
      :wrapper-col="wrapperCol"
      :model="formData"
      :rules="getFormRules"
      ref="formRef"
    >
      <FormItem name="Email" class="enter-x" :label="t('viewmodal.sendEmail.email')">
        <Input
          size="large"
          v-model:value="formData.Email"
          :placeholder="t('viewmodal.sendEmail.emailPlaceholder')"
        >
          <template #prefix>
            <Icon icon="carbon-email" />
          </template>
        </Input>
      </FormItem>

      <FormItem name="VerifyCode" class="enter-x" :label="t('viewmodal.sendEmail.verifyCode')">
        <CaptchaInput
          size="large"
          v-model:value="formData.VerifyCode"
          :placeholder="t('viewmodal.sendEmail.verifyCodePlaceholder')"
          :getCaptchaApi="refreshVerifyCode"
          icon="flat-color-icons:edit-image"
        />
      </FormItem>
    </Form>
  </AdVxeModal>
</template>
<script lang="ts" setup>
  import type { PropType } from 'vue';
  import type { Rule } from 'ant-design-vue/es/form';
  import { reactive, unref, ref } from 'vue';
  import { AdVxeModal, useModalInner } from '@/components/AdVxeModal';
  import { Form, Input } from 'ant-design-vue';
  import { RuleObject } from 'ant-design-vue/lib/form/interface';
  import { CaptchaInput } from '@/components/Captcha';
  import Icon from '@/components/Icon/Icon.vue';

  import { useI18n } from '@/hooks/web/useI18n';
  import { isFunction } from '@/utils/is';
  import { propTypes } from '@/utils/propTypes';

  import { getVerifyCode, checkVerifyCode } from '@/api/sys';
  import { isEmail } from '@/enums/regexEnum';
  import { checkEmailExists } from '@/api/identity';

  /** 发送邮件DTO */
  export interface SendEmailDto {
    /** 电子邮箱 */
    Email: string;
    /** 邮箱确认地址 */
    EmailConfirmUrl?: string;

    /** 验证码 */
    VerifyCode?: string;
    /** 验证码编号 */
    VerifyCodeId?: string;
  }

  const FormItem = Form.Item;

  defineOptions({ name: 'SendEmail' });
  const props = defineProps({
    /** 标题 */
    sendTitle: propTypes.string.def(''),
    /** 验证邮箱是否存在，默认 undefined */
    checkEmailExist: propTypes.bool.def(undefined),
    /** 确定前回调，返回true关闭窗体 */
    beforeOkFunc: {
      type: Function as PropType<(data: SendEmailDto) => Promise<boolean>>,
      default: null,
    },
  });

  const { t } = useI18n();
  const formRef = ref();

  const formData: SendEmailDto = reactive({
    Email: '',
    EmailConfirmUrl: '',
    VerifyCode: '',
    VerifyCodeId: '',
  });

  const [register, { closeModal, changeOkLoading }] = useModalInner((data) => {
    formData.Email = data.email;
    formData.EmailConfirmUrl = data.emailConfirmUrl;
    formData.VerifyCode = '';
    formData.VerifyCodeId = '';
  });

  /** 获取表单规则 */
  const getFormRules: Record<string, Rule[]> = {
    Email: [
      {
        required: true,
        validator: async (_: RuleObject, value: string) => {
          if (!value) {
            return Promise.reject(t('viewmodal.sendEmail.emailPlaceholder'));
          }
          if (!isEmail(value)) {
            return Promise.reject(t('viewmodal.sendEmail.emailFormatError'));
          }
          if (props.checkEmailExist !== undefined) {
            const isExist = await checkEmailExists(value);
            if (props.checkEmailExist && isExist) {
              return Promise.reject(t('viewmodal.sendEmail.emailExisted'));
            }
            if (!props.checkEmailExist && !isExist) {
              return Promise.reject(t('viewmodal.sendEmail.emailNotExisted'));
            }
          }
          return Promise.resolve();
        },
        trigger: 'change',
      },
    ],
    VerifyCode: [
      {
        required: true,
        validator: async (_: RuleObject, value: string) => {
          if (value === undefined || value === null || value === '') {
            return Promise.reject(t('viewmodal.sendEmail.verifyCodePlaceholder'));
          }
          if (
            formData.VerifyCodeId === undefined ||
            formData.VerifyCodeId === null ||
            formData.VerifyCodeId === ''
          ) {
            return Promise.reject(t('viewmodal.sendEmail.verifyCodeInvalid'));
          }
          if (!(await checkVerifyCode(value, formData.VerifyCodeId))) {
            return Promise.reject(t('viewmodal.sendEmail.verifyCodeInvalid'));
          }
          return Promise.resolve();
        },
        trigger: 'change',
      },
    ],
  };

  /** 验证表单 */
  const validForm = async () => {
    const form = unref(formRef);
    if (!form) return;
    const data = await form.validate();
    return data;
  };

  /** 刷新验证码 */
  async function refreshVerifyCode() {
    const verifyCodeDto = await getVerifyCode();
    formData.VerifyCodeId = verifyCodeDto.Id;
    return verifyCodeDto.Image;
  }

  /** 处理确定 */
  async function handleOk() {
    const { beforeOkFunc } = props;
    const data = await validForm();
    if (!data) return;

    if (beforeOkFunc && isFunction(beforeOkFunc)) {
      changeOkLoading(true);
      try {
        const canClose = await beforeOkFunc(formData);
        if (canClose) {
          clearFormData();
          closeModal();
        }
      } finally {
        changeOkLoading(false);
      }
    } else {
      clearFormData();
      closeModal();
    }
  }

  /** 处理取消 */
  async function handleClose() {
    clearFormData();
    return true;
  }

  /** 清除表单数据 */
  function clearFormData() {
    formData.Email = '';
    formData.EmailConfirmUrl = '';
    formData.VerifyCode = '';
    formData.VerifyCodeId = '';
  }

  const labelCol = { span: 6 };
  const wrapperCol = { span: 16 };
</script>
